AWS Step Functionsステートマシンの結合テストをしたい(実行成功確認)
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、AWS Step Functionsステートマシンの結合テストをする方法を確認してみました。
ステートマシンの実行結果の評価がうまく行えない
AWS上に作成をしたStep Functionsステートマシンに対する動作確認(いわゆる結合テスト)を行いたい場合があります。
テスト対象は、このようなLambda関数を1つ実行するタスクがある5秒程度で終了するステートマシンとします。
そこで次のような、ステートマシンをAWS SDKで実行して実行結果が成功(SUCCEEDED
)となることを確認するテストコードを作成しました。
import * as AWS from 'aws-sdk'; const sfn = new AWS.StepFunctions({ region: 'ap-northeast-1', }); const STATE_MACHINE_ARN = process.env.STATE_MACHINE_ARN as string; test('ステートマシンの実行が成功することを確認', async (): Promise<void> => { //テスト対象のステートマシンを実行 const execution = await sfn .startExecution({ stateMachineArn: STATE_MACHINE_ARN, }) .promise(); const executionArn = execution.executionArn; //ステートマシンの実行情報を取得 const executionDescription = await sfn .describeExecution({ executionArn: executionArn }) .promise(); //ステートマシンの実行が成功していることを確認 expect(executionDescription.status).toBe('SUCCEEDED'); });
DescribeExecutionで確認できるステートマシンの実行ステータスの値は次のようなものがあります。このうちSUCCEEDED
となれば成功、FAILED
やTIMED_OUT
となれば失敗であることが分かります。
status
The current status of the execution.
Type: String
Valid Values: RUNNING | SUCCEEDED | FAILED | TIMED_OUT | ABORTED
Jestでテストを実行します。するとステートマシンの実行ステータスがRUNNING
(実行中)の状態でexpect()
による評価が行われてしまい、成功か失敗かの評価がうまく行えませんでした。
$ npx jest FAIL test/stateMachine.test.ts (6.628 s) ✕ ステートマシンの実行が成功することを確認 (298 ms) ● ステートマシンの実行が成功することを確認 expect(received).toBe(expected) // Object.is equality Expected: "SUCCEEDED" Received: "RUNNING" 20 | .promise(); 21 | > 22 | expect(executionDescription.status).toBe('SUCCEEDED'); | ^ 23 | }); 24 | at Object.<anonymous> (test/stateMachine.test.ts:22:39) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 6.684 s, estimated 8 s Ran all test suites.
これはstartExecution
によるステートマシンの実行は非同期となるためです。
待機時間を設けることによりうまく行えた
そこでwhile
とsetTimeout
による待機時間を設けます。ステートマシンの実行ステータスがRUNNING
の間は待機をするようにします。
import * as AWS from 'aws-sdk'; const sfn = new AWS.StepFunctions({ region: 'ap-northeast-1', }); const STATE_MACHINE_ARN = process.env.STATE_MACHINE_ARN as string; test('ステートマシンの実行が成功することを確認', async (): Promise<void> => { //テスト対象のステートマシンを実行 const execution = await sfn .startExecution({ stateMachineArn: STATE_MACHINE_ARN, }) .promise(); const executionArn = execution.executionArn; //ステートマシンの実行ステータスがRUNNINGでなくなるまで待機 let executionStatus = 'RUNNING'; while (executionStatus === 'RUNNING') { await new Promise((r) => setTimeout(r, 1000)); let res = await sfn .describeExecution({ executionArn: executionArn }) .promise(); if (res.status !== 'RUNNING') executionStatus = res.status; } //ステートマシンの実行情報を取得 const executionDescription = await sfn .describeExecution({ executionArn: executionArn }) .promise(); //ステートマシンの実行が成功していることを確認 expect(executionDescription.status).toBe('SUCCEEDED'); });
するとJestによる実行結果の評価を行えるようになりました。
$ npx jest PASS test/stateMachine.test.ts (8.251 s) ✓ ステートマシンの実行が成功することを確認 (1769 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 8.299 s Ran all test suites.
startSyncExecutionは使えないのか?
今回、テストコードからステートマシンを実行するためにstartExecution
を使用しました。このメソッドは標準ワークフローのステートマシンの実行にのみ利用可能です。今回テストを行いたかったのは標準ワークフローとなります。
StartExecution is idempotent for STANDARD workflows. For a STANDARD workflow, if StartExecution is called with the same name and input as a running execution, the call will succeed and return the same response as the original request.
もうひとつステートマシンを実行できるメソッドとしてStartSyncExecution
というものがありますが、これは標準ワークフローのステートマシンには使用できません。Expressワークフローのものに対してのみ使用できます。
Starts a Synchronous Express state machine execution. StartSyncExecution is not available for STANDARD workflows.
両者の違いとしては、標準ワークフローの実行は非同期のみとなりますが、Expressワークフローは同期での実行が可能となります。
当初、これを使用すると名前的にステートマシンの同期実行ができそうな気がして使ってみたのですが、標準ワークフローのステートマシンであったため、案の定エラーとなりました。
import * as AWS from 'aws-sdk'; const sfn = new AWS.StepFunctions({ region: 'ap-northeast-1', }); const STATE_MACHINE_ARN = process.env.STATE_MACHINE_ARN as string; test('ステートマシンの実行', async (): Promise<void> => { const execution = await sfn .startSyncExecution({ stateMachineArn: STATE_MACHINE_ARN, }) .promise(); console.log(execution); });
StateMachineTypeNotSupported: This operation is not supported by this type of state machine
というエラーとなっています。
$ npx jest FAIL test/stateMachine.test.ts (6.506 s) ✕ ステートマシンの実行 (179 ms) ● ステートマシンの実行 StateMachineTypeNotSupported: This operation is not supported by this type of state machine at Request.extractError (node_modules/aws-sdk/lib/protocol/json.js:52:27) at Request.callListeners (node_modules/aws-sdk/lib/sequential_executor.js:106:20) at Request.emit (node_modules/aws-sdk/lib/sequential_executor.js:78:10) at Request.emit (node_modules/aws-sdk/lib/request.js:686:14) at Request.transition (node_modules/aws-sdk/lib/request.js:22:10) at AcceptorStateMachine.runTo (node_modules/aws-sdk/lib/state_machine.js:14:12) at node_modules/aws-sdk/lib/state_machine.js:26:10 at Request.<anonymous> (node_modules/aws-sdk/lib/request.js:38:9) at Request.<anonymous> (node_modules/aws-sdk/lib/request.js:688:12) at Request.callListeners (node_modules/aws-sdk/lib/sequential_executor.js:116:18) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 6.555 s, estimated 11 s Ran all test suites.
以上